#ifndef ESP32
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif

#include <Arduino.h>
#include <U8g2lib.h>
#include "Wire.h"
#include "SHT2x.h"
#include <EEPROM.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#include <Wire.h> // Library for I2C communication
#include <SPI.h>  // not used here, but needed to prevent a RTClib compile error
// #include "RTClib.h"
#include <EEPROM.h>
// 自动配网
#include <WiFiManager.h>
WiFiManager wm;
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <RX8010.h>
// #include <TM1650.h>

#include <SPI.h>
#include <SD.h>
#define SD_CS 15
// #define SD_CS 5
File myFile;
#include <PubSubClient.h>
// char mqtt_server[] = "h3253k9765.oicp.vip";
//  char mqtt_server[] = "lubo1982.myqnapcloud.cn";
const char *mqtt_server = "192.168.3.254";
const char *mqttUser = "lu";
const char *mqttPassWd = "5891381";
const int port = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
// #pragma execution_character_set("gb2312")

dateTime dt;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp.aliyun.com", 8 * 3600, 60000);
uint8_t macAddr[6];
String Host;
uint32_t last;
uint32_t stop;
int voltage[5] = {0, 0, 0, 0, 0};
SHT2x sht;
bool netConnectionStatus = 0;
bool timeUpdateStatus = 0;
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/SCL, /* data=*/SDA, /* reset=*/U8X8_PIN_NONE); // All Boards without Reset of the Display
void netSetup()
{
    bool res;
    WiFi.mode(WIFI_STA);
    wm.setTimeout(180);
    u8g2.clearBuffer();
    u8g2.drawUTF8(0, 15, "连网中");
    u8g2.sendBuffer();
    char Host[20];
    //   wm.resetSettings();
    sprintf(Host, "AutoConnect-%x%x%x", macAddr[3], macAddr[4], macAddr[5]);
    res = wm.autoConnect(Host);
    if (!res)
    {
        Serial.println("Failed to connect");
    }
    else
    {
        Serial.println("connectedis...yeey :)");
        u8g2.drawUTF8(60, 15, "OK");
        u8g2.sendBuffer();
    }
}
bool linkToMqtt()
{
    // MQTT
    client.setServer(mqtt_server, port);
    client.setCallback(callback);
    reconnect();
    subScribe();
    if (client.connected())
        return 1;
    else
        return 0;
}
void subScribe()
{
    client.subscribe("POT/Switch");
    client.subscribe("POT/Set");
    client.subscribe("POT/OTA");
}
void callback(char *topic, byte *payload, unsigned int length)
{
    String message, top;
    int powerButton, tempButton, autoMode, OTAOrder;
    int setState, setTime; // serState是设置开机时间还是关机时间。0是关机时间，1是开机时间

    top = topic;

    for (int i = 0; i < length; i++)
    {
        message += (char)payload[i];
    }
    Serial.printf("R:[%s] %s\n", top.c_str(), message.c_str());
    // 直接控制水壶按键,并设置自动开关机状态。
    /*   if (top == "POT/Switch")
      {
          ;
      } */
    // 设置自动开关机时间，如果第一位数字是0，则设置关机时间，数字是1设置开机时间。
}
dateTime timeSync()
{
    dateTime dt;
    u8g2.drawUTF8(0, 31, "时间同步");
    u8g2.sendBuffer();
    if (timeClient.update())
    {
        dt.year = timeClient.getYear() - 2000;
        dt.month = timeClient.getMonth();
        dt.date = timeClient.getDate();
        dt.day = timeClient.getDay();
        dt.hour = timeClient.getHours();
        dt.minute = timeClient.getMinutes();
        dt.second = timeClient.getSeconds();
        Serial.println("Time sync OK");
    }
    u8g2.drawUTF8(60, 31, "OK");
    u8g2.sendBuffer();
    return dt;
}
void reconnect()
{
    int i = 0;
    // Loop until we're reconnected
    while (!client.connected())
    {
        if (i++ > 3)
            break;
        Serial.print("Attempting MQTT connection...");
        if (client.connect(Host.c_str(), mqttUser, mqttPassWd))
        {
            Serial.println("connected");
        }
        else
        {
            Serial.print("failed, rc=");
            Serial.println(client.state());

            delay(100);
        }
    }
    subScribe();
}
IRAM_ATTR void timeUpdate()
{
    timeUpdateStatus = 1;
}
void drawWiFiIcon()
{
    // 绘制 WiFi 图标的天线部分
    u8g2.drawLine(127, 0, 127, 15);
    u8g2.drawLine(123, 5, 123, 15);
    u8g2.drawLine(119, 12, 119, 15);
    // 绘制 WiFi 图标的信号部分
    //   u8g2.drawCircle(50, 40, 8);
    //   u8g2.drawCircle(46, 40, 4);

    // 绘制 WiFi 图标的背景部分
    //    u8g2.drawRectangle(10, 20, 70, 40);
    u8g2.sendBuffer();
}
void timeUpdateFunction()
{
    char buf[80], fileName[20];
    String msg = "";
    dateTime m;
    float vol = calVol();
    m = getDateTime();
    sht.read();
    u8g2.clearBuffer();
    sprintf(buf, "%02d-%02d-%02d %02d:%02d:%02d\n", m.year, m.month, m.date, m.hour, m.minute, m.second);
    u8g2.drawUTF8(0, 15, buf); // write something to the internal memory
    sprintf(buf, "%.1f°C", sht.getTemperature());
    u8g2.drawUTF8(0, 31, buf);
    sprintf(buf, "%.1f%%", sht.getHumidity());
    u8g2.drawUTF8(63, 31, buf);
    sprintf(buf, "%.2fV", vol);
    u8g2.drawUTF8(0, 46, buf);
    if (netConnectionStatus)
    {
        u8g2.drawLine(127, 3, 127, 15);
        u8g2.drawLine(123, 8, 123, 15);
        u8g2.drawLine(119, 12, 119, 15);
    }
    u8g2.sendBuffer();
    sprintf(buf, "%02d-%02d-%02d %02d:%02d:%02d,temp:%.1f°C,humi:%.1f%%,volt:%.2fV,%s", m.year, m.month, m.date, m.hour, m.minute, m.second, sht.getTemperature(), sht.getHumidity(), vol, (netConnectionStatus ? "Online" : "Offline"));
    Serial.println(buf);

    if (m.second == 0)
    {
        sprintf(fileName, "Record%02d%02d%02d.txt", m.year, m.month, m.date);
        myFile = SD.open(fileName, FILE_WRITE);
        if (myFile)
        {
            myFile.println(buf);
            myFile.close();
        }
        else
            Serial.println("SD card error1");
    }
    if (m.second % 5 == 0)
    {
        if (netConnectionStatus)
        {
            sprintf(buf, "{\"time\":\"%02d:%02d:%02d\",\"temp\":%.1f,\"humi\":%.1f,\"volt\":%.2f}", m.hour, m.minute, m.second, sht.getTemperature(), sht.getHumidity(), vol);
            char topic[6];
            sprintf(topic, "%x%x%x", macAddr[3], macAddr[4], macAddr[5]);
            client.publish(topic, buf);
            Serial.printf("T:[%s]%s\n", topic, buf);
        }
    }
}

void setup(void)
{
    u8g2.begin();
    sht.begin();
    Serial.begin(115200);
    uint8_t stat = sht.getStatus();
    Serial.print(stat, HEX);
    Serial.println();
    sht.heatOff();
    sht.setResolution(0);
    u8g2.setFont(u8g2_font_wqy15_t_gb2312);
    pinMode(12, INPUT_PULLUP);
    pinMode(SD_CS, OUTPUT);
    WiFi.macAddress(macAddr);
    Host = "Test-" + macAddr[4] + macAddr[5];
    if (digitalRead(12) == 0)
    {
        netSetup();
        linkToMqtt();
        timeClient.begin();
        if (timeClient.update())
        {
            setTime(timeSync());
        }
    }
    setTUIMode(0);
    enableTUI();
    if (!SD.begin(SD_CS))
    {
        Serial.println("SD card error");
    }
    attachInterrupt(2, timeUpdate, RISING);
}
double calVol()
{
    int v = 0;
    for (int i = 0; i < 4; i++)
    {
        voltage[i] = voltage[i + 1];
        v += voltage[i];
    }
    voltage[4] = analogRead(A0);
    v += voltage[4];
    return (v / 5) * 0.004944;
}
void loop(void)
{
    int i = 0;
    char buf[60];
    client.loop();
    if (millis() - last > 100)
    {
        calVol();
        if (WiFi.status() != WL_CONNECTED)
            netConnectionStatus = 0;
        else
        {
            netConnectionStatus = 1;
            if (!client.connected())
                reconnect();
            //    sprintf(buf, "temp:%.1f°C,humi:%.1f%%,volt:%.2fV", sht.getTemperature(), sht.getHumidity(), vol);
            //   client.publish("Test/Status", "a");
        }
        last = millis();
    }
    if (timeUpdateStatus == 1)
    {
        timeUpdateStatus = 0;
        timeUpdateFunction();
    }
    //    timeUpdateFunction();
}
